package org.taobao.ibatiside.ui.wizard;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.List;
import java.util.Map;

import org.eclipse.emf.codegen.merge.java.JControlModel;
import org.eclipse.emf.codegen.merge.java.JMerger;
import org.eclipse.emf.codegen.merge.java.facade.ast.ASTFacadeHelper;
import org.eclipse.emf.ecore.EObject;
import org.taobao.ibatiside.ui.wizard.BatisSettingModelArgument.BatisSettingModelArgumentResult;
import org.taobao.ibatiside.ui.wizard.BatisSettingModelArgument._Field_Type;

public final class CreateBatisSettingModel {

	/**
	 * @param args
	 * @throws FileNotFoundException 
	 */
	public static void main(String[] args) throws FileNotFoundException {
		File file = new File("src/org/taobao/ibatiside/ui/wizard/BatisSettingModel.java");
		Field[] fields = BatisSettingModelArgument.class.getDeclaredFields();
		BatisSettingModelArgumentResult result = new BatisSettingModelArgumentResult();
		for (Field f : fields){
			Class<?> ft = f.getType();
			if (needImport(ft)){
				result.addImport(ft.getCanonicalName());
			}
			_Field_Type field = new _Field_Type();
			field.name = f.getName();
			field.type = ft.getSimpleName();
			field.category = 1;
			if (List.class.isAssignableFrom(ft)){
				field.category = 2;
				ParameterizedType ptt = (ParameterizedType) f.getGenericType();
				Class<?> pt = (Class<?>) ptt.getActualTypeArguments()[0];
				if (needImport(pt)){
					result.addImport(pt.getCanonicalName());
				}
				field.slot1 = pt.getSimpleName();
			}else if (Map.class.isAssignableFrom(ft)){
				field.category = 3;
				ParameterizedType ptt = (ParameterizedType) f.getGenericType();
				Class<?> pt1 = (Class<?>) ptt.getActualTypeArguments()[0];
				Class<?> pt2 = (Class<?>) ptt.getActualTypeArguments()[1];
				if (needImport(pt1)){
					result.addImport(pt1.getCanonicalName());
				}
				if (needImport(pt2)){
					result.addImport(pt2.getCanonicalName());
				}
				field.slot1 = pt1.getSimpleName();
				field.slot2 = pt2.getSimpleName();
			}else if (EObject.class.isAssignableFrom(ft)){
				field.category = 4;
			}
			result.addField(field);
		}
		String output = new BatisSettingModelGen().generate(result);
		JControlModel control_model = new JControlModel();
		ASTFacadeHelper ast_helper = new ASTHelper();
		control_model.initialize(ast_helper, CreateBatisSettingModel.class.getResource("merger-config.xml").toString());
		JMerger merger = new JMerger(control_model);
		FileInputStream inputStream = new FileInputStream(file);
		merger.setSourceCompilationUnit(merger.createCompilationUnitForContents(output));
		merger.setTargetCompilationUnit(merger.createCompilationUnitForInputStream(inputStream));
		merger.merge();
		String merged_output = merger.getTargetCompilationUnitContents();
		try {
			inputStream.close();
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		try {
			FileWriter writer = new FileWriter(file);
			writer.write(merged_output);
			writer.close();
			System.out.println("Generating setting model was finished!");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private static boolean needImport(Class<?> ft) {
		boolean to_import = !ft.isPrimitive();
		String fqn = ft.getCanonicalName();
		to_import = to_import && ! fqn.startsWith("java.lang.");
		to_import = to_import && ! fqn.startsWith(BatisSettingModel.class.getPackage().getName());
		return to_import;
	}

}
